jetcrab\lexer\scanners/
number.rs1use crate::lexer::{LexerError, TokenKind};
2
3pub trait NumberReader {
4 fn read_number(&mut self) -> Result<TokenKind, LexerError>;
5}
6
7impl<T> NumberReader for T
8where
9 T: LexerCore,
10{
11 fn read_number(&mut self) -> Result<TokenKind, LexerError> {
12 let mut number = String::new();
13 let mut is_hex = false;
14 let mut is_binary = false;
15 let mut is_octal = false;
16
17 if self.source()[self.pos()] == '0' && self.pos() + 1 < self.source().len() {
18 match self.source()[self.pos() + 1] {
19 'x' | 'X' => {
20 is_hex = true;
21 number.push('0');
22 number.push(self.source()[self.pos() + 1]);
23 self.advance_pos();
24 self.advance_pos();
25 }
26 'b' | 'B' => {
27 is_binary = true;
28 number.push('0');
29 number.push(self.source()[self.pos() + 1]);
30 self.advance_pos();
31 self.advance_pos();
32 }
33 'o' | 'O' => {
34 is_octal = true;
35 number.push('0');
36 number.push(self.source()[self.pos() + 1]);
37 self.advance_pos();
38 self.advance_pos();
39 }
40 _ => {}
41 }
42 }
43
44 while self.pos() < self.source().len() {
45 let c = self.source()[self.pos()];
46
47 if is_hex {
48 if c.is_ascii_hexdigit() {
49 number.push(c);
50 self.advance_pos();
51 } else {
52 break;
53 }
54 } else if is_binary {
55 if c == '0' || c == '1' {
56 number.push(c);
57 self.advance_pos();
58 } else {
59 break;
60 }
61 } else if is_octal {
62 if ('0'..='7').contains(&c) {
63 number.push(c);
64 self.advance_pos();
65 } else {
66 break;
67 }
68 } else if c.is_ascii_digit() || c == '.' || c == 'e' || c == 'E' || c == '+' || c == '-'
69 {
70 number.push(c);
71 self.advance_pos();
72 } else {
73 break;
74 }
75 }
76
77 if self.pos() < self.source().len() && self.source()[self.pos()] == 'n' {
78 number.push('n');
79 self.advance_pos();
80 return Ok(TokenKind::BigInt(number));
81 }
82
83 if is_hex {
84 match u64::from_str_radix(&number[2..], 16) {
85 Ok(n) => Ok(TokenKind::Number(n as f64)),
86 Err(_) => Err(LexerError::InvalidNumber(number)),
87 }
88 } else if is_binary {
89 match u64::from_str_radix(&number[2..], 2) {
90 Ok(n) => Ok(TokenKind::Number(n as f64)),
91 Err(_) => Err(LexerError::InvalidNumber(number)),
92 }
93 } else if is_octal {
94 match u64::from_str_radix(&number[2..], 8) {
95 Ok(n) => Ok(TokenKind::Number(n as f64)),
96 Err(_) => Err(LexerError::InvalidNumber(number)),
97 }
98 } else {
99 match number.parse::<f64>() {
100 Ok(n) => Ok(TokenKind::Number(n)),
101 Err(_) => Err(LexerError::InvalidNumber(number)),
102 }
103 }
104 }
105}
106
107use crate::lexer::scanners::LexerCore;